package com.equis.estacionamientos.bean.polygon {
	import com.google.maps.LatLng;
	import com.google.maps.LatLngBounds;
	import com.google.maps.Map;
	import com.google.maps.interfaces.IMap;
	import com.google.maps.overlays.EncodedPolylineData;
	import com.google.maps.overlays.Polygon;
	import com.google.maps.overlays.PolygonOptions;
	import com.google.maps.styles.FillStyle;
	import com.google.maps.styles.StrokeStyle;
	/*
	* http://groups.google.com/group/google-maps-api-for-flash/browse_thread/thread/d55a8109fde92cd2/5528444a75c99c1b?lnk=gst&q=hole#5528444a75c99c1b
	* http://code.google.com/p/pabrowser/source/browse/trunk/pabrowser/src/org/gbif/maps/PolylineEncoder.as
	* http://code.google.com/p/pabrowser/source/browse/trunk/pabrowser/src/pabrowser.mxml
	*/

	public class PolygonManager {
	
		private var _polygon:Polygon;
		private var _capiPolygon:Polygon;
	    private var _map:IMap;
	    
	    private var internalPolygon:Array = [new LatLng(-34.696094, -58.460026), new LatLng(-34.66052, -58.42844),
	        new LatLng(-34.654872, -58.417797), new LatLng(-34.656284, -58.396854),
	        new LatLng(-34.65346, -58.379345), new LatLng(-34.647246, -58.354282),
	        new LatLng(-34.63962, -58.339863), new LatLng(-34.61589, -58.345699),
	        new LatLng(-34.590456, -58.363209), new LatLng(-34.571235, -58.395824),
	        new LatLng(-34.551727, -58.435307), new LatLng(-34.53787, -58.464146),
	        new LatLng(-34.551444, -58.494358), new LatLng(-34.615042, -58.525257),
	        new LatLng(-34.651483, -58.523197), new LatLng(-34.663909, -58.508434),
	        new LatLng(-34.697788, -58.462429)];
		
		private var outerCapiPoints:Array = [
			new LatLng(-33.475898,-59.997254),
			new LatLng(-34.160455,-60.826721),
			new LatLng(-34.979152,-61.024475),
			new LatLng(-36.136544,-60.041199),
			new LatLng(-36.265093,-57.898865),
			new LatLng(-35.682733,-56.355286),
			new LatLng(-34.096795,-55.904846),
			new LatLng(-33.264872,-57.657166),
			new LatLng(-33.14997,-58.898621),
			new LatLng(-33.475898,-59.997254)
        ];
		
		private var innerCapiPoints:Array = [
			new LatLng(-34.53450152906624, -58.46504656850649),
			new LatLng(-34.54596112325458, -58.49179225753461),
			new LatLng(-34.54946204077694, -58.49911460306642),
			new LatLng(-34.55057211335913, -58.50038559215318),
			new LatLng(-34.59050006495784, -58.5191412639166),
			new LatLng(-34.60879055560626, -58.52785729235312),
			new LatLng(-34.61555445502901, -58.5310776968153),
			new LatLng(-34.65336713208465, -58.52871593787834),
			new LatLng(-34.67779128763741, -58.49765900549133),
			new LatLng(-34.69490650914791, -58.47454673620549),
			new LatLng(-34.70492083211, -58.46073367907324),
			new LatLng(-34.66372069243265, -58.42572727281523),
			new LatLng(-34.66159029269095, -58.42267227157966),
			new LatLng(-34.65965769680021, -58.41724660104906),
			new LatLng(-34.65882825221149, -58.4142038485387),
			new LatLng(-34.65863538725256, -58.41274833146781),
			new LatLng(-34.65916192687432, -58.41041718185266),
			new LatLng(-34.66012717505334, -58.4081455084954),
			new LatLng(-34.66029393895048, -58.40669594256838),
			new LatLng(-34.6596792272664, -58.40358010459659),
			new LatLng(-34.65980324774828, -58.40205251086864),
			new LatLng(-34.66060179644164, -58.40081530968807),
			new LatLng(-34.66105859746505, -58.39984966479116),
			new LatLng(-34.6608217458983, -58.39888139424058),
			new LatLng(-34.65893080388165, -58.39911362355461),
			new LatLng(-34.65837966896771, -58.39832759902067),
			new LatLng(-34.65867674117264, -58.39686418075987),
			new LatLng(-34.65933027256562, -58.39604212045613),
			new LatLng(-34.65972952482611, -58.39588695818868),
			new LatLng(-34.66027392462972, -58.39626774243226),
			new LatLng(-34.66061302751363, -58.39727911497499),
			new LatLng(-34.66126232449248, -58.39810717174981),
			new LatLng(-34.66172200370861, -58.39793189471563),
			new LatLng(-34.66217057390543, -58.39750622767085),
			new LatLng(-34.66232673913811, -58.39662913704741),
			new LatLng(-34.66218401156847, -58.39543123060025),
			new LatLng(-34.66254831823122, -58.39302689395471),
			new LatLng(-34.66228576570887, -58.39157654569517),
			new LatLng(-34.66130668242609, -58.39047842973224),
			new LatLng(-34.66069419440201, -58.38849176752966),
			new LatLng(-34.6602976095808, -58.38731255297317),
			new LatLng(-34.6590550107858, -58.38641968621757),
			new LatLng(-34.65847924290876, -58.38585238313372),
			new LatLng(-34.65794961914843, -58.38481722509187),
			new LatLng(-34.65778250904438, -58.38042766293513),
			new LatLng(-34.65728222108286, -58.37741590360179),
			new LatLng(-34.65695992553996, -58.37415421263525),
			new LatLng(-34.65468340495342, -58.37099625978208),
			new LatLng(-34.65356437372362, -58.36942507247788),
			new LatLng(-34.65118859582521, -58.36852816945965),
			new LatLng(-34.64868866338693, -58.36397200397217),
			new LatLng(-34.64799066076243, -58.36125082002089),
			new LatLng(-34.6459015486555, -58.35870327664112),
			new LatLng(-34.64456359805744, -58.35653845855057),
			new LatLng(-34.64012072234003, -58.35824073260474),
			new LatLng(-34.63714317567158, -58.35449648118462),
			new LatLng(-34.63595795702711, -58.35258126316966),
			new LatLng(-34.62776184597689, -58.33193499942698),
			new LatLng(-34.61111994281012, -58.33920007062321),
			new LatLng(-34.59994914131305, -58.34587711886206),
			new LatLng(-34.58732915129698, -58.35435982328787),
			new LatLng(-34.5606351350898, -58.39003528263186),
			new LatLng(-34.52621524182909, -58.45736887704364),
			new LatLng(-34.52621601328834, -58.45736692320629),
			new LatLng(-34.52621661431693, -58.45736444183609),
			new LatLng(-34.52621695199485, -58.45736269607027),
			new LatLng(-34.52621514326494, -58.45736453508407),
			new LatLng(-34.52621771448837, -58.45736584504211),
			new LatLng(-34.52617896288275, -58.45740370061436),
			new LatLng(-34.52613544570894, -58.45743775015406),
			new LatLng(-34.53450152906624, -58.46504656850649),
		];
	    
		public function PolygonManager(map:IMap) {
	        _map = map;
	        buildPolygon();
	    }
	
	    private function buildPolygon():void {
			_polygon = new Polygon(internalPolygon, new PolygonOptions({
	            strokeStyle: new StrokeStyle({
	                thickness: 1,
	                alpha: 0.7
	            }),
	            fillStyle: new FillStyle({
	                alpha: 0.7})
	        		}));
			_polygon.visible = false;
	         
			var myEncoder:PolylineEncoder = new PolylineEncoder(18,2,0.00001,true);
			var encodedPolyLines:Array = new Array();                       
			
			var outer:Object = myEncoder.dpEncode(outerCapiPoints);
			encodedPolyLines.push(new EncodedPolylineData(outer.encodedPoints, 2, outer.encodedLevels, 18));
			
			var inner:Object = myEncoder.dpEncode(innerCapiPoints);
			encodedPolyLines.push(new EncodedPolylineData(inner.encodedPoints, 2, inner.encodedLevels, 18));
			var polOpt:PolygonOptions = new PolygonOptions({ 
                strokeStyle: new StrokeStyle({
                    color: 0x000000,
                    thickness: 1,
                    alpha: 1}), 
                fillStyle: new FillStyle({
                    color: 0x000000,
                    alpha: 0.7})
                });             
                                
            _capiPolygon = Polygon.fromEncoded(encodedPolyLines, polOpt);
            _map.addOverlay(_capiPolygon);
	        _map.addOverlay(_polygon);
	
	    }
	
	    public function checkMoveOutsidePolygon():void {
	        var latlongbounds:LatLngBounds = _map.getLatLngBounds();
	        var latlongboundsPolygon:LatLngBounds = _polygon.getLatLngBounds();
	        if (latlongbounds.intersects(latlongboundsPolygon) || latlongbounds.containsBounds(latlongboundsPolygon)) {
	            _map.savePosition();
	        } else {
	            _map.returnToSavedPosition();
	        }
	    }
	    
		/**
	    * Add a circle to the global variable "map". This function won't work for circles that encompass
	    * the North or South Pole. Also, there is a slight distortion in the upper-left, upper-right,
	    * lower-left, and lower-right sections of the circle that worsens as it gets larger and/or closer
	    * to a pole.
	    * @param map The Map
	    * @param lat Latitude in degrees
	    * @param lng Longitude in degrees
	    * @param radius Radius of the circle in statute miles
	    * @param {String} strokeColor Color of the circle outline in HTML hex style, e.g. "#FF0000"
	    * @param strokeWidth Width of the circle outline in pixels
	    * @param strokeOpacity Opacity of the circle outline between 0.0 and 1.0
	    * @param {String} fillColor Color of the inside of the circle in HTML hex style, e.g. "#FF0000"
	    * @param fillOpacity Opacity of the inside of the circle between 0.0 and 1.0
	    */
		public static function drawCircleInMap(map:Map, lat:Number, lng:Number, radius:Number, strokeColor:Number, strokeWidth:Number, strokeOpacity:Number, fillColor:Number, fillOpacity:Number):Polygon {
	        var d2r:Number = Math.PI/180;
	        var r2d:Number = 180/Math.PI;
	        var circleLat:Number = radius * 0.014483;  // Convert statute miles into degrees latitude
	        var circleLng:Number = circleLat/Math.cos(lat*d2r); 
	        var circleLatLngs:Array = new Array();
	        for (var i:Number = 0; i < 33; i++) { 
	        	var theta:Number = Math.PI * (i/16); 
	            var vertexLat:Number = lat + (circleLat * Math.sin(theta)); 
	            var vertexLng:Number = lng + (circleLng * Math.cos(theta)); 
	            var latLng:LatLng = new LatLng(vertexLat, vertexLng); 
	            circleLatLngs.push(latLng); 
			}
	      
			var polygonOptions:PolygonOptions = new PolygonOptions();
			var fillStyle:FillStyle = new FillStyle();
			fillStyle.alpha = fillOpacity;
			fillStyle.color = fillColor;
			polygonOptions.fillStyle = fillStyle; 
			
			var strokeStyle:StrokeStyle = new StrokeStyle();
			strokeStyle.alpha = strokeOpacity;
			strokeStyle.color = strokeColor;
			strokeStyle.thickness = strokeWidth;
			polygonOptions.strokeStyle = strokeStyle
			var polygon:Polygon = new Polygon(circleLatLngs, polygonOptions); 
			map.addOverlay(polygon);
			return polygon;
	    }
	    
		public static function pointInPolygon(point:LatLng,polygon:Polygon):Boolean {
			var j:Number=0;
			var func_oddNodes:Boolean = false;
			var x:Number = point.lng();
			var y:Number = point.lat();
			for (var i:Number=0; i < polygon.getOuterVertexCount(); i++) {
				j++;
				if (j == polygon.getOuterVertexCount()) {
					j = 0;
				}
				if (((polygon.getOuterVertex(i).lat() < y) 
					&& (polygon.getOuterVertex(j).lat() >= y))
					|| ((polygon.getOuterVertex(j).lat() < y) 
					&& (polygon.getOuterVertex(i).lat() >= y))) {
			
					if ( polygon.getOuterVertex(i).lng() + (y -
					polygon.getOuterVertex(i).lat())
					/  (polygon.getOuterVertex(j).lat()-
					polygon.getOuterVertex(i).lat())
					*  (polygon.getOuterVertex(j).lng() -
					polygon.getOuterVertex(i).lng())<x ) {
					func_oddNodes = !func_oddNodes
				}
				}
			}
			return func_oddNodes;
		}
	}
}
